#include <jni.h>
#include <stdio.h>
#include <string.h>
//#include <malloc.h>
#include <stdlib.h>
//"333333333333333333333333333333333333333"
#define IDEAKEYSIZE 16
#define IDEABLOCKSIZE 8
#define word16 unsigned short 
#define word32 unsigned long 
#define ROUNDS	8
#define KEYLEN	(6*ROUNDS+4)
#define FILELENG (5*1024*1024)
#define RECVBYTE 1024+1    //  传送数据 或得crc32 文件

#define low16(x) ((x) & 0xffff)

typedef unsigned short uint16;
typedef word16 IDEAkey[KEYLEN];

#define CRC32C_POLY 0x1EDC6F41
#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])

unsigned long crc_c[256] =
{
	0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
	0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
	0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
	0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
	0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
	0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
	0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
	0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
	0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
	0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
	0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
	0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
	0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
	0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
	0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
	0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
	0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
	0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
	0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
	0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
	0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
	0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
	0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
	0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
	0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
	0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
	0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
	0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
	0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
	0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
	0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,

	0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
	0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
	0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
	0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
	0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
	0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
	0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
	0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
	0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
	0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
	0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
	0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
	0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
	0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
	0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
	0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
	0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
	0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
	0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
	0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
	0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
	0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
	0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
	0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
	0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
	0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
	0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
	0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
	0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
	0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
	0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
	0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
	0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L,
};


unsigned long reflect_32 (unsigned long b)
{
	int i;
	unsigned long rw = 0L;

	for (i = 0; i < 32; i++){
		if (b & 1)
			rw |= 1 << (31 - i);
		b >>= 1;
	}
	return (rw);
}
//计算码表元素
unsigned long build_crc_table (int index,unsigned long p_CRC32C_POLY)
{
	int i;
	unsigned long rb;

	rb = reflect_32 (index);

	for (i = 0; i < 8; i++){
		if (rb & 0x80000000L)
			rb = (rb << 1) ^ p_CRC32C_POLY;
		else
			rb <<= 1;
	}
	return (reflect_32 (rb));
}
//通用CRC32算法，方法为：如果是最后1次计算则flag赋1，否则赋0
unsigned long   generate_crc32(unsigned long poly, unsigned long  init_value,unsigned char *buffer, unsigned int length ,long flag)
{
	unsigned int i;
	//unsigned long crc32 = ~0L;
	unsigned long crc32 =init_value;
	unsigned long result;
	unsigned char byte0,byte1,byte2,byte3;

	for (i = 0; i < length; i++){
		//#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
		//CRC32C(crc32, buffer[i]);
		//crc32=(crc32>>8)^crc_c[(crc32^(buffer[i]))&0xFF];
		crc32=(crc32>>8)^build_crc_table((crc32^(buffer[i]))&0xFF,poly);
	}

	if(flag==1)
	{
		result = ~crc32;

		byte0 =(unsigned char)( result & 0xff);
		byte1 = (unsigned char)((result>>8) & 0xff);
		byte2=(unsigned char)( (result>>16) & 0xff);
		byte3 = (unsigned char)((result>>24) & 0xff);

		crc32 = ((byte0 << 24) |  (byte1 << 16) | (byte2 << 8) | byte3);

	}
	return ( crc32 );
}


static uint16 inv(uint16 x)
{
	uint16 t0,t1;
	uint16 q,y;
	if (x<=1)
		return x;
	t1=(uint16)(0x10001l/x);
	y=(uint16)(0x10001l%x);
	if (y==1)
		return low16(1-t1);
	t0=1;
	do
	{
		q=x/y;
		x=x%y;
		t0+=q*t1;
		if (x==1)
			return t0;
		q=y/x;
		y=y%x;
		t1+=q*t0;
	} while (y!=1);
	return low16(1-t1);
}

static void en_key_idea(unsigned short  *userkey, unsigned short  *Z)
{
	short i,j;
	/* shifts */
	for (j=0;j<8;j++)
		Z[j]=*userkey++;
	for (i=0;j<KEYLEN;j++)
	{
		i++;
		Z[i+7]=((Z[i&7] << 9) | (Z[i+1 & 7] >> 7));
		Z+=i&8;
		i&=7;
	}
}

static void de_key_idea(IDEAkey Z,IDEAkey DK)
{
	short j;
	uint16 t1,t2,t3;
	IDEAkey T;
	unsigned short  *p=T+KEYLEN;
	t1=inv(*Z++);
	t2=-*Z++;
	t3=-*Z++;
	*--p=inv(*Z++);
	*--p=t3;
	*--p=t2;
	*--p=t1;
	for (j=1;j<ROUNDS;j++)
	{
		t1=*Z++;
		*--p=*Z++;
		*--p=t1;
		t1=inv(*Z++);
		t2=-*Z++;
		t3=-*Z++;
		*--p=inv(*Z++);
		*--p=t2;
		*--p=t3;
		*--p=t1;
	}
	t1=*Z++;
	*--p=*Z++;
	*--p=t1;
	t1=inv(*Z++);
	t2=-*Z++;
	t3=-*Z++;
	*--p=inv(*Z++);
	*--p=t3;
	*--p=t2;
	*--p=t1;
	/*copy and destroy temp copy*/
	for(j=0,p=T;j<KEYLEN;j++)
	{
		*DK++=*p;
		*p++=0;
	}
}


uint16 mul(uint16 a, uint16 b)
{
	unsigned long  p;

	if (a)
	{
		if (b)
		{
			p=(unsigned long )a*b;
			b=(uint16)(low16(p));
			a=(uint16)(p>>16);
			return b-a+(b<a);
		}
		else
		{
			return 1-a;
		}
	}
	else
		return 1-b;
}

#define MUL(x,y) (x=mul(low16(x),y))




static void cipher_idea(unsigned short  in[4],unsigned short  out[4],register const IDEAkey Z)
{
	register uint16 x1,x2,x3,x4,t1,t2;
	short r=ROUNDS;
	x1=*in++; x2=*in++;
	x3=*in++; x4=*in;
	do
	{
		MUL(x1,*Z++);
		x2+=*Z++;
		x3+=*Z++;
		MUL(x4,*Z++);
		t2=x1^x3;
		MUL(t2,*Z++);
		t1=t2+(x2^x4);
		MUL(t1,*Z++);
		t2=t1+t2;
		x1^=t1;
		x4^=t2;
		t2^=x2;
		x2=x3^t1;
		x3=t2;
	} while (--r);
	MUL(x1,*Z++);
	*out++=x1;
	*out++=(x3+*Z++);
	*out++=(x2+*Z++);
	MUL(x4,*Z);
	*out=x4;
}

void Asc2ToHex(char* pStr,char* pOut)
{
	int ii = 0;
	int jj = 0;
	char tempChar = 0x00;
	char srcStr[RECVBYTE] = {0};
	char tempBuf[RECVBYTE/2] ={0};
	while (1)
	{
		if(pStr[ii]==0)
		{
			break;
		}
		ii++;
	}
	ii++;
	memcpy(srcStr,pStr,ii);
	ii = 0;
	jj = 0;
	for (;srcStr[ii]!=0;ii++)
	{

		if(srcStr[ii]>='0' &&pStr[ii]<='9')
		{
			srcStr[ii] = srcStr[ii] - 0x30;
		}
		else //0x0A - 0x0F
		{
			srcStr[ii] = srcStr[ii] - 0x37;
		}
		if (ii%2 == 0)
		{
			tempChar = 0x00;
			tempChar = srcStr[ii]<<4;
			tempChar &=0xF0;

		}//1A70B8BE26C994DA88F4712F5E60C73b
		else
		{
			tempChar += srcStr[ii];

			memcpy(&tempBuf[jj],&tempChar,sizeof(tempChar));
			jj++;
		}

	}
	memcpy(pOut,tempBuf,ii/2);
}

void HexToAsc2(char* dst,char* src,int len) //HEX to ASCII
{
	//len 为 RECVBYTE/2 = HEX 数据长度
	char tempBuf[RECVBYTE] ={0};
	int jj = 0;
	int ii = 0;
	int unicodelen = len*2;
	for(;ii<len;ii++)
	{

		char temp[2] = {0};

		temp[0] = src[ii]>>4;    //字符高半位
		temp[0] &= 0x0F;
		if(temp[0]>=0 &&temp[0]<=9)
		{
			temp[0]+=0x30;
		}
		else //0x0A - 0x0F
		{
			temp[0]+=0x37;
		}

		temp[1] =(src[ii]&0x0F); //字符低半位
		if(temp[1]>=0 &&temp[1]<=9)
		{
			temp[1]+=0x30;
		}
		else //0x0A - 0x0F
		{
			temp[1]+=0x37;
		}

		memcpy(&tempBuf[jj],temp,sizeof(temp));
		jj+=2;

	}
	memcpy(dst,tempBuf,len*2);


}


/*
IDEA加密算法：16B密钥加密8B明文得到8B密文
*/
jstring  Java_com_util_IDEAUtil_encodingCode(JNIEnv * env, jobject thiz, jstring jstrKey, jstring jstrData)
{
	unsigned short  input[4],output[4];
	unsigned char myKey[100] ={0};
	unsigned char out[8];
	unsigned char dst[100]={0};
    //char testStr[]="123456";
	//在这转换数据
	//…………
	char* test = (*env)->GetStringUTFChars(env,jstrData,NULL); //使用完毕后 应调用：ReleaseStringUTFChars
	char* test1 = (*env)->GetStringUTFChars(env,jstrKey,NULL);
    Asc2ToHex(test,input);
	Asc2ToHex(test1,myKey);
	//memcpy((unsigned char*)input,test,8);  //拷贝被加密数据
	//memcpy(myKey,test1,8);				   //拷贝钥匙
	(*env)->ReleaseStringUTFChars(env, jstrData, test);
	(*env)->ReleaseStringUTFChars(env, jstrKey, test1);

	IDEAkey Z;


	en_key_idea((unsigned short *)myKey,Z); //钥匙
	cipher_idea(input,output,Z);   //被加密数据input

	memcpy(out,(unsigned char*)output,8);



	HexToAsc2(dst,out,8);

	return (*env)->NewStringUTF(env,dst);


}


/*
IDEA解密算法：16B密钥解密8B密文得到8B明文
*/
jstring  Java_com_util_IDEAUtil_decodingCode (JNIEnv * env, jobject thiz, jstring jstrKey, jstring jstrData)
{
	unsigned short  input[4],output[4];
	unsigned char myKey[100] ={0};
	unsigned char out[8];
	unsigned char dst[100]={0};

    char* test =(*env)->GetStringUTFChars(env,jstrData,NULL);
	char* test1 =(*env)->GetStringUTFChars(env,jstrKey,NULL);
	Asc2ToHex(test,input);
	Asc2ToHex(test1,myKey);
	//memcpy((unsigned char*)input,test,8); //拷贝被加密数据
    //memcpy(myKey,test1,8);   //拷贝钥匙
	(*env)->ReleaseStringUTFChars(env, jstrData, test);
	(*env)->ReleaseStringUTFChars(env, jstrKey, test1);

	IDEAkey Z,DK;


	en_key_idea((unsigned short *)myKey,Z);
	de_key_idea(Z,DK);
	cipher_idea(input,output,DK);
	memcpy(out,(unsigned char*)output,8);


	HexToAsc2(dst,out,8);
    return (*env)->NewStringUTF(env,dst);

}




// 比较CRC32
//jboolean Java_com_util_IDEAUtil_compare
int crc = 0;
jboolean Java_com_util_IDEAUtil_compareCRC32 (JNIEnv * env, jobject thiz,int poly,int csz,int jstrCrc,jstring jstrFileLeng,jstring jstrData,jboolean isFind)
{
   unsigned char tempBuf[RECVBYTE/2]={0};


//	unsigned int   iCrc  = 0;   //正确的crc32
//	int   iLeng = 0;   //文件长度

   // char* pstrCrc =(*env)->GetStringUTFChars(env,jstrCrc,NULL);
   // char* pstrFileLeng =(*env)->GetStringUTFChars(env,jstrFileLeng,NULL);

	//iCrc = atoi(pstrCrc);
	//iLeng =atoi(pstrFileLeng);
	//iCrc = pstrCrc;
	//iLeng =pstrFileLeng;

	//(*env)->ReleaseStringUTFChars(env, jstrCrc, pstrCrc);
	//(*env)->ReleaseStringUTFChars(env, jstrFileLeng, pstrFileLeng);

     char* pjstrData = (*env)->GetStringUTFChars(env,jstrData,NULL);
   
	if (isFind==0)
	{   

		Asc2ToHex(pjstrData,(char*)tempBuf);
	    crc = generate_crc32(poly,csz,tempBuf,jstrFileLeng,0);
		(*env)->ReleaseStringUTFChars(env, jstrData, pjstrData);

	}
	else
	{
	 
		Asc2ToHex(pjstrData,(char*)tempBuf);
		crc = generate_crc32(poly,crc,tempBuf,jstrFileLeng,1); 
		(*env)->ReleaseStringUTFChars(env, jstrData, pjstrData);
		if(jstrCrc == crc)
		{
			return  1;
		}

	}
       
	return 0;
	 
}
 
 